﻿using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Server
{
    public class AsyncTcpServer
    {
        private const int Port = 29100;
        private const int BufferSize = 1024;
        private readonly Socket _serverSocket;
        private readonly List<Socket> _clientSockets = new List<Socket>();
        private readonly object _lock = new object();

        public AsyncTcpServer()
        {
            JsonUtility.SetJsonHelper(new NewtonsoftJsonHelper());
            _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        public void Start()
        {
            try
            {
                // 绑定到本地端点
                _serverSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
                _serverSocket.Listen(100); // 允许最多100个挂起连接
                Console.WriteLine($"服务器已启动，监听端口 {Port}...");

                // 开始接受客户端连接
                StartAccept();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"服务器启动错误: {ex.Message}");
            }
        }

        private void StartAccept()
        {
            try
            {
                // 开始异步接受连接
                _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接受连接错误: {ex.Message}");
            }
        }

        private void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                // 完成接受连接操作
                Socket clientSocket = _serverSocket.EndAccept(ar);

                // 将客户端添加到列表
                lock (_lock) _clientSockets.Add(clientSocket);
                Console.WriteLine($"客户端已连接: {clientSocket.RemoteEndPoint}");

                // 开始接收来自此客户端的数据
                StartReceive(clientSocket);

                // 继续接受其他客户端连接
                StartAccept();
            }
            catch (ObjectDisposedException)
            {
                // 服务器已关闭
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接受连接回调错误: {ex.Message}");
                StartAccept(); // 继续接受其他连接
            }
        }

        private void StartReceive(Socket clientSocket)
        {
            try
            {
                // 创建状态对象
                StateObject state = new StateObject();
                state.WorkSocket = clientSocket;

                // 开始异步接收数据
                clientSocket.BeginReceive(state.Buffer, 0, BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"开始接收错误: {ex.Message}");
                CloseClientSocket(clientSocket);
            }
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            // 从状态对象中获取信息
            StateObject state = (StateObject)ar.AsyncState;
            Socket clientSocket = state.WorkSocket;

            try
            {
                // 完成接收操作
                int bytesRead = clientSocket.EndReceive(ar);

                if (bytesRead > 0)
                {
                    // 处理接收到的数据
                    var data = state.Buffer;
                    int offset = 0;
                    var packetLength = data.ReadUInt(ref offset);
                    var operationType = data.ReadByte(ref offset);
                    var zipFlag = data.ReadByte(ref offset);
                    var uniqueId = data.ReadInt(ref offset);
                    var id = data.ReadInt(ref offset);

                    string message = Encoding.UTF8.GetString(state.Buffer, 0, bytesRead);
                    Console.WriteLine($"来自 {clientSocket.RemoteEndPoint}: {message}");

                    if (id == 655370)
                    {
                        var heartBeat = new ResHeartBeat();
                        // 发送响应
                        string response = $"服务器已收到: {message}";
                        //byte[] responseBytes = Encoding.UTF8.GetBytes(response);
                        byte[] responseBytes = heartBeat.Serialize();

                        // 开始异步发送响应
                        clientSocket.BeginSend(responseBytes, 0, responseBytes.Length, 0,
                            new AsyncCallback(SendCallback), clientSocket);
                    }
                    else if (id == 655380)
                    {
                        var resServerTime = new ResServerTime();
                        byte[] responseBytes = resServerTime.Serialize();

                        // 开始异步发送响应
                        clientSocket.BeginSend(responseBytes, 0, responseBytes.Length, 0,
                            new AsyncCallback(SendCallback), clientSocket);
                    }
                    else if (id == 655590)
                    {
                        var resTestRpc = new ResTestRpc(uniqueId);
                        byte[] responseBytes = resTestRpc.Serialize();
                        // 开始异步发送响应
                        clientSocket.BeginSend(responseBytes, 0, responseBytes.Length, 0,
                            new AsyncCallback(SendCallback), clientSocket);
                    }
       

                    // 继续接收更多数据
                    StartReceive(clientSocket);
                }
                else
                {
                    // 客户端断开连接
                    Console.WriteLine($"客户端断开连接: {clientSocket.RemoteEndPoint}");
                    CloseClientSocket(clientSocket);
                }
            }
            catch (SocketException sex)
            {
                Console.WriteLine($"接收数据错误: {sex.SocketErrorCode} - {sex.Message}");
                CloseClientSocket(clientSocket);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收回调错误: {ex.Message}");
                CloseClientSocket(clientSocket);
            }
        }

        private void SendCallback(IAsyncResult ar)
        {
            Socket clientSocket = (Socket)ar.AsyncState;

            try
            {
                // 完成发送操作
                int bytesSent = clientSocket.EndSend(ar);
                Console.WriteLine($"已发送 {bytesSent} 字节到 {clientSocket.RemoteEndPoint}");
            }
            catch (SocketException sex)
            {
                Console.WriteLine($"发送数据错误: {sex.SocketErrorCode} - {sex.Message}");
                CloseClientSocket(clientSocket);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发送回调错误: {ex.Message}");
                CloseClientSocket(clientSocket);
            }
        }

        private void CloseClientSocket(Socket clientSocket)
        {
            try
            {
                lock (_lock)
                {
                    if (_clientSockets.Contains(clientSocket))
                    {
                        clientSocket.Shutdown(SocketShutdown.Both);
                        clientSocket.Close();
                        _clientSockets.Remove(clientSocket);
                        Console.WriteLine($"客户端已断开: {clientSocket.RemoteEndPoint}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"关闭客户端Socket错误: {ex.Message}");
            }
        }

        public void Stop()
        {
            try
            {
                // 关闭所有客户端连接
                lock (_lock)
                {
                    foreach (var socket in _clientSockets)
                    {
                        try
                        {
                            socket.Shutdown(SocketShutdown.Both);
                            socket.Close();
                        }
                        catch { }
                    }
                    _clientSockets.Clear();
                }

                // 关闭服务器Socket
                _serverSocket.Close();
                Console.WriteLine("服务器已停止");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"停止服务器错误: {ex.Message}");
            }
        }

        // 状态对象用于在异步调用之间传递信息
        private class StateObject
        {
            public Socket WorkSocket = null;
            public byte[] Buffer = new byte[BufferSize];
        }
    }
}